home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / c / library / dos / diverses / leda / src / plane / _polygon.bak < prev    next >
Encoding:
Text File  |  1991-11-15  |  8.0 KB  |  399 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  2.1.1                                                 11-15-1991
  4. +
  5. +
  6. +  _polygon.c
  7. +
  8. +
  9. +  Copyright (c) 1991  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15. #include <LEDA/plane.h>
  16. #include <math.h>
  17.  
  18. #ifndef __TURBOC__
  19. #include <LEDA/plane_alg.h>
  20. declare(edge_array,bool)
  21. #endif
  22.  
  23.  
  24. //------------------------------------------------------------------------------
  25. // polygons
  26. //------------------------------------------------------------------------------
  27.  
  28.  
  29. polygon_rep::polygon_rep(list(segment) L) 
  30.   seg_list = L;
  31.   count = 1; 
  32.  }
  33.  
  34. polygon_rep::polygon_rep()         { count = 1; }
  35.  
  36. polygon::polygon()                 { ptr = new polygon_rep; }
  37. polygon::polygon(int)              { ptr = new polygon_rep; }
  38. polygon::polygon(polygon& P)       { ptr = P.ptr; ptr->count++; }
  39. polygon::polygon(ent x)            { ptr=(polygon_rep*)x; ptr->count++; }
  40. void polygon::clear()              { if (--(ptr->count)==0) delete ptr; }
  41.  
  42.  
  43. ostream& operator<<(ostream& out, const polygon& p) 
  44. { p.vertices().print();
  45.   return out;
  46.  } 
  47.  
  48. istream& operator>>(istream& in,  polygon& p) 
  49. { list(point) L; 
  50.   L.read(); 
  51.   p = polygon(L); 
  52.   return in;
  53. }
  54.  
  55.  
  56. void polygon_check(list(segment)&);
  57.  
  58. polygon::polygon(list(point)& pl, bool check)
  59. { ptr = new polygon_rep;
  60.  
  61.   list_item it,it1;
  62.  
  63.   forall_list_items(it,pl)
  64.   { it1 = pl.cyclic_succ(it);
  65.     ptr->seg_list.append(segment(pl[it],pl[it1]));
  66.    }
  67.  
  68.   if (check) polygon_check(ptr->seg_list);
  69. }
  70.  
  71. list(point) polygon::vertices() const
  72. { list(point) result;
  73.   segment s;
  74.   forall(s,ptr->seg_list) result.append(s.start());
  75.   return result;
  76. }
  77.  
  78.  
  79.  
  80.  
  81. void polygon_check(list(segment)& seg_list)
  82. {  if (seg_list.length() < 3) 
  83.      error_handler(1,"polygon: must be simple");
  84.  
  85. #ifndef __TURBOC__
  86.    list(point) L;
  87.    SWEEP_SEGMENTS(seg_list,L);
  88.  
  89.   if (L.length() != seg_list.length())
  90.    error_handler(1,"polygon: must be simple");
  91. #endif
  92.  
  93.   list_item it;
  94.  
  95.   double angle = 0;
  96.  
  97.   forall_list_items(it,seg_list)
  98.   { list_item succ = seg_list.cyclic_succ(it);
  99.     segment s1 = seg_list[it];
  100.     segment s2 = seg_list[succ];
  101.     angle += s1.angle(s2);
  102.    }
  103.  
  104.   if (angle > 0)
  105.    error_handler(1,"polygon: point list must be clockwise oriented.");
  106. }
  107.  
  108. polygon polygon::translate(double alpha, double d)
  109. { list(point) L;
  110.   segment s;
  111.   forall(s,ptr->seg_list) L.append(s.start().translate(alpha,d));
  112.   return polygon(L,false);
  113. }
  114.  
  115. polygon polygon::translate(const vector& v)
  116. { list(point) L;
  117.   segment s;
  118.   forall(s,ptr->seg_list) L.append(s.start().translate(v));
  119.   return polygon(L,false);
  120. }
  121.  
  122. polygon polygon::rotate(point origin, double alpha)
  123. { list(point) L;
  124.   segment s;
  125.   forall(s,ptr->seg_list) L.append(s.start().rotate(origin,alpha));
  126.   return polygon(L,false);
  127. }
  128.  
  129. polygon polygon::rotate(double alpha)
  130. { return rotate(point(0,0),alpha);
  131.  }
  132.  
  133.  
  134. /*
  135.  
  136. bool polygon::inside(point p)
  137. {
  138.   line l(p,M_PI_2);  // vertical line through p
  139.  
  140.   int count = 0;
  141.  
  142.   segment s;
  143.   forall(s,ptr->seg_list)
  144.   { point q;
  145.     if (!l.intersection(s,q)) continue;
  146.     if (q.ycoord() < p.ycoord()) continue;
  147.     if (q == s.start())  continue;
  148.     if (q == s.end())  continue;
  149.     count++ ;
  150.    }
  151.  
  152.   list(point) plist = vertices();
  153.  
  154.   list_item i = plist.first();;
  155.  
  156.   forall_items(i,plist)
  157.   { 
  158.     point q = plist[i];
  159.  
  160.     if (q==p) return true;
  161.  
  162.     if (q.xcoord() == p.xcoord() && q.ycoord() > p.ycoord())
  163.     { list_item i0 = plist.cyclic_pred(i);
  164.       list_item i1 = plist.cyclic_succ(i);
  165.       point q0 = plist[i0];
  166.       point q1 = plist[i1];
  167.  
  168.       if (q0.xcoord() < p.xcoord() && q1.xcoord() > p.xcoord()) count++;
  169.       if (q0.xcoord() > p.xcoord() && q1.xcoord() < p.xcoord()) count++;
  170.  
  171.      }
  172.  
  173.    }
  174.  
  175.    return count%2;
  176.  
  177. }
  178.  
  179. */
  180.  
  181.  
  182.  
  183. bool polygon::inside( point p)
  184. {
  185.   line l(p,M_PI_2);  // vertical line through p
  186.  
  187.   int count = 0;
  188.  
  189.   segment s;
  190.   forall(s,ptr->seg_list)
  191.   { point q;
  192.     if (!l.intersection(s,q)) continue;
  193.     if (q.ycoord() < p.ycoord()) continue;
  194.     if (q == s.start())  continue;
  195.     if (q == s.end())  continue;
  196.     count++ ;
  197.    }
  198.  
  199.   list(point) plist = vertices();
  200.  
  201.   list_item i0 = plist.first();
  202.  
  203.   while (plist[i0].xcoord() == p.xcoord())  i0 = plist.cyclic_pred(i0);
  204.  
  205.   list_item i = plist.cyclic_succ(i0);
  206.  
  207.   for(;;)
  208.   { 
  209.     while ( i != i0 && (plist[i].xcoord() != p.xcoord() || 
  210.                         plist[i].ycoord() < p.ycoord()    )  )
  211.        i = plist.cyclic_succ(i);
  212.  
  213.     if (i==i0) break;
  214.  
  215.     point q  = plist[i];
  216.     point q0 = plist[plist.cyclic_pred(i)];
  217.  
  218.     while ((plist[i].xcoord()==p.xcoord()) && (plist[i].ycoord() >= p.ycoord()))
  219.     { if (plist[i]==p) return true;
  220.       i = plist.cyclic_succ(i);
  221.      }
  222.  
  223.     point q1 = plist[i];
  224.  
  225.      if (q0.xcoord() < p.xcoord() && q1.xcoord() > p.xcoord()) count++;
  226.       if (q0.xcoord() > p.xcoord() && q1.xcoord() < p.xcoord()) count++;
  227.  
  228.    }
  229.  
  230.    return count%2;
  231.  
  232. }
  233.  
  234. bool polygon::outside(point p) { return !inside(p); }
  235.  
  236.  
  237. list(point) polygon::intersection(segment s)
  238. { list(point) result;
  239.   segment t;
  240.   point p;
  241.  
  242.   forall(t,ptr->seg_list) 
  243.     if (s.intersection(t,p))
  244.      if (result.empty()) result.append(p);
  245.      else if (p != result.tail() ) result.append(p);
  246.  
  247.   return result;
  248. }
  249.  
  250.  
  251. list(point) polygon::intersection(line l)
  252. { list(point) result;
  253.   segment t;
  254.   point p;
  255.  
  256.   forall(t,ptr->seg_list) 
  257.     if (l.intersection(t,p))
  258.      if (result.empty()) result.append(p);
  259.      else if (p != result.tail() ) result.append(p);
  260.  
  261.   return result;
  262. }
  263.  
  264.  
  265. // intersection with polygon
  266.  
  267. #ifndef __TURBOC__
  268.  
  269. static bool polygon_test_edge(GRAPH(point,int)& G,edge& i1)
  270. { node v = G.target(i1);
  271.  
  272.   edge e,i2=nil,o1=nil,o2=nil;
  273.  
  274.   forall_adj_edges(e,v)
  275.     if (e != i1)
  276.     { if (v==target(e)) i2 = e;
  277.       else if (G[e]== G[i1]) o1 = e;
  278.            else o2 = e;
  279.      }
  280.  
  281.   if (i2==nil) return false;
  282.  
  283.   segment si1(G[source(i1)],G[v]);
  284.   segment si2(G[v],G[source(i2)]);
  285.   segment so2(G[v],G[target(o2)]);
  286.  
  287.   double alpha = si1.angle(si2);
  288.   double beta  = si1.angle(so2);
  289.  
  290.   return (alpha > beta);
  291.  
  292. }
  293.  
  294.  
  295.  
  296. static edge polygon_switch_edge(GRAPH(point,int)& G,edge i1)
  297. { node v = G.target(i1);
  298.  
  299.   edge e,i2=nil,o1=nil,o2=nil;
  300.  
  301.   forall_adj_edges(e,v)
  302.     if (e != i1)
  303.     { if (v==target(e)) i2 = e;
  304.       else if (G[e]== G[i1]) o1 = e;
  305.            else o2 = e;
  306.      }
  307.  
  308.   if (i2==nil) return  o1;
  309.  
  310.   segment si1(G[source(i1)],G[v]);
  311.   segment si2(G[v],G[source(i2)]);
  312.   segment so1(G[v],G[target(o1)]);
  313.   segment so2(G[v],G[target(o2)]);
  314.  
  315.   double alpha = si1.angle(si2);
  316.   double beta  = si1.angle(so2);
  317.   double gamma = si1.angle(so1);
  318.  
  319.   if (alpha < beta) cout << "error: alpa < beta!!\n";
  320.  
  321.   if (gamma >= beta) return o2;
  322.   else return o1;
  323.  
  324. }
  325.  
  326. #endif
  327.  
  328. list(polygon) polygon::intersection(polygon P)
  329. {
  330.  
  331.   list(polygon) result;
  332.  
  333. #ifndef __TURBOC__
  334.  
  335.   GRAPH(point,int) SUB;
  336.  
  337.   SWEEP_SEGMENTS(segments(),P.segments(),SUB);
  338.  
  339.   int N = SUB.number_of_nodes();
  340.  
  341.   if (N < size() + P.size())
  342.    error_handler(1,"polygon: sorry, internal error in intersection");
  343.  
  344.   if (N == size() + P.size())
  345.   { // no intersections between edges of (*this) and P
  346.     // check for inclusion
  347.  
  348.     segment s1 = ptr->seg_list.head();
  349.     segment s2 = P.ptr->seg_list.head();
  350.     point   p1 = s1.start();
  351.     point   p2 = s2.start();
  352.  
  353.     if (P.inside(p1))                     // (*this) is conained in P
  354.       result.append(*this);
  355.     else
  356.       if (inside(p2))                     // P is conained in (*this)
  357.         result.append(P);                   
  358.  
  359.  
  360.     return result;
  361.  
  362.    }
  363.  
  364.   SUB.make_undirected();
  365.  
  366.   edge e;
  367.  
  368.   list(point) PL;
  369.  
  370.   edge_array(bool) marked(SUB,false);
  371.  
  372.   forall_edges(e,SUB) 
  373.   { edge f;
  374.     if (!marked[e]  && SUB.outdeg(target(e))>1) 
  375.       if (polygon_test_edge(SUB,e))
  376.       { // new polygon found
  377.        marked[e] = true;
  378.        PL.append(SUB[source(e)]);
  379.        f = polygon_switch_edge(SUB,e);
  380.        while (f!=e)
  381.        { marked[f] = true;
  382.          PL.append(SUB[source(f)]);
  383.          f = polygon_switch_edge(SUB,f);
  384.         }
  385.        result.append(polygon(PL,false));
  386.        PL.clear();
  387.       }
  388.   }
  389.  
  390.  SUB.make_directed();
  391.  
  392. #endif
  393.  
  394.  return result;
  395.  
  396. }
  397.